package com.fxn.pix;

import com.fxn.modals.Img;
import com.fxn.modals.Options;
import com.fxn.interfaces.OnRecordStopListener;
import com.fxn.interfaces.OnSelectionListener;
import com.fxn.interfaces.OnVerticalListSelectionListener;
import com.fxn.component.CameraView;
import com.fxn.component.MyBottomSheet;
import com.fxn.adapters.InstantImageAdapter;
import com.fxn.adapters.MainImageAdapter;

import com.fxn.utils.ToastUtil;
import com.fxn.utils.FileUtils;
import com.fxn.utils.Utility;
import com.fxn.utils.LogUtil;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.Component;
import ohos.agp.components.Image;
import ohos.agp.components.Text;
import ohos.agp.components.ListContainer;
import ohos.agp.components.StackLayout;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.app.dispatcher.TaskDispatcher;
import ohos.app.dispatcher.task.Revocable;
import ohos.app.dispatcher.task.TaskPriority;
import ohos.data.resultset.ResultSet;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.global.resource.NotExistException;
import ohos.media.camera.device.CameraConfig;
import ohos.media.camera.params.Metadata;
import ohos.media.image.ImageReceiver;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.ImageFormat;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;
import ohos.media.photokit.metadata.AVMetadataHelper;
import ohos.media.photokit.metadata.AVStorage;
import ohos.multimodalinput.event.TouchEvent;
import ohos.utils.net.Uri;

import java.io.IOException;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Set;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Locale;
import java.util.Calendar;

/**
 * description : Pix 照相机和文件列表页面
 *
 * @since 2021-04-15
 */
public class Pix extends Ability implements Component.ClickedListener {
    /**
     * Pix选中的图片的list集合
     */
    public static final String IMAGE_RESULTS = "image_result";
    private static final String TAG = "TakePictureAbilitySlice";
    private static final int NOTIFY_PROVIDER = 100;

    private EventHandler cameraEventHandler;
    private CameraView cameraView;
    private String picturePath;
    private int flashMode = Metadata.FlashMode.FLASH_CLOSE;

    // 定义生成图片文件名
    private String pictureName = "picture_001.jpg";

    private Image takePic;
    private Image takePicBg;
    private MyBottomSheet mBottomSheet;
    private StackLayout sendButton;
    private StackLayout mScrollbar;
    private StackLayout topbar;
    private StackLayout bottomButtons;
    private StackLayout flash;
    private StackLayout shiftCamera;
    private Text selection_count;
    private Text img_count;
    private Text selection_ok;
    private Text bottomMessage;
    private Image mHandleView;
    private Image selection_back;
    private Image selection_check;
    private Image arrow_up;
    private ListContainer horizontalList;
    private ListContainer verticalList;
    private boolean isFrontCamera = false;
    private Options options = null;
    private final Set<Img> selectionList = new HashSet<>();
    private boolean LongSelection = false;
    private MainImageAdapter mMainImageAdapter;
    private InstantImageAdapter mInstantImageAdapter;
    private ArrayList<Img> mList = new ArrayList<>();
    private TaskDispatcher mParallelTaskDispatcher;
    private final String dispatcherName = "parallelTaskDispatcher";
    private Revocable mRevocable;

    // 创建一个自动控制的EventRunner
    private EventRunner eventRunner = EventRunner.getMainEventRunner();
    private MyEventHandler mHandler = new MyEventHandler(eventRunner);
    private CameraConfig.Builder mCameraConfigBuilder;
    private final OnVerticalListSelectionListener onVtcListListener = new OnVerticalListSelectionListener() {
        @Override
        public void onClick(Img img, Component view, int firstPos, int position) {
            if (LongSelection) {
                if (selectionList.contains(img)) {
                    selectionList.remove(img);
                    mMainImageAdapter.select(false, firstPos, position);
                    mInstantImageAdapter.select(false, img.getPosition());
                } else {
                    if (options.getCount() <= selectionList.size()) {
                        ToastUtil.showShort(Pix.this,
                                String.format(Locale.ROOT, "Can't select more than %d items.", selectionList.size()));
                        return;
                    }
                    selectionList.add(img);
                    mInstantImageAdapter.select(true, img.getPosition());
                    mMainImageAdapter.select(true, firstPos, position);
                }
                if (selectionList.size() == 0) {
                    LongSelection = false;
                    selection_check.setVisibility(Component.VISIBLE);
                    try {
                        PixelMapElement pixelMapElement = null;
                        pixelMapElement =
                                new PixelMapElement(getResourceManager().getResource(ResourceTable.Media_back));
                        selection_back.setBackground(pixelMapElement);
                    } catch (IOException | NotExistException e) {
                        e.printStackTrace();
                    }
                    ShapeElement background = new ShapeElement();
                    background.setRgbColor(RgbColor.fromRgbaInt(Color.getIntColor("#ffffffff")));
                    topbar.setBackground(background);
                    sendButton.setVisibility(Component.HIDE);
                }
                selection_count.setText(selectionList.size() + " Selected");
                img_count.setText(String.valueOf(selectionList.size()));
            } else {
                selectionList.add(img);
                returnImages();
                try {
                    PixelMapElement pixelMapElement = null;
                    pixelMapElement =
                            new PixelMapElement(getResourceManager().getResource(ResourceTable.Media_back));
                    selection_back.setBackground(pixelMapElement);
                } catch (IOException | NotExistException e) {
                    e.printStackTrace();
                }
                ShapeElement background = new ShapeElement();
                background.setRgbColor(RgbColor.fromRgbaInt(Color.getIntColor("#ffffffff")));
                topbar.setBackground(background);
            }
        }

        @Override
        public void onLongClick(Img img, Component view, int firstPos, int position) {
            if (options.getCount() > 1) {
                LongSelection = true;
                if (selectionList.size() == 0 && (mBottomSheet.getStatus() != MyBottomSheet.Status.ON_TOP)) {
                    sendButton.setVisibility(Component.VISIBLE);
                    sendButton.createAnimatorProperty()
                            .scaleXFrom(0).scaleX(1)
                            .scaleYFrom(0).scaleY(1)
                            .setDuration(300);
                }
                if (selectionList.contains(img)) {
                    selectionList.remove(img);
                    mInstantImageAdapter.select(false, img.getPosition());
                    mMainImageAdapter.select(false, firstPos, position);
                } else {
                    if (options.getCount() <= selectionList.size()) {
                        ToastUtil.showShort(Pix.this,
                                String.format(Locale.ROOT, "Can't select more than %d items.", selectionList.size()));
                        return;
                    }
                    selectionList.add(img);
                    mInstantImageAdapter.select(true, img.getPosition());
                    mMainImageAdapter.select(true, firstPos, position);
                }
                selection_check.setVisibility(Component.HIDE);
                ShapeElement background = new ShapeElement();
                background.setRgbColor(RgbColor.fromRgbaInt(Color.getIntColor("#075e54ff")));
                topbar.setBackground(background);
                selection_count.setText(selectionList.size() + " Selected");
                img_count.setText(String.valueOf(selectionList.size()));
                try {
                    PixelMapElement pixelMapElement = null;
                    pixelMapElement =
                            new PixelMapElement(getResourceManager().getResource(ResourceTable.Media_white_back));
                    selection_back.setBackground(pixelMapElement);
                } catch (IOException | NotExistException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private final OnSelectionListener onSelectionListener = new OnSelectionListener() {
        @Override
        public void onClick(Img img, Component view, int position) {
            if (LongSelection) {
                if (selectionList.contains(img)) {
                    selectionList.remove(img);
                    mInstantImageAdapter.select(false, position);
                    mMainImageAdapter.select(false, img);
                } else {
                    if (options.getCount() <= selectionList.size()) {
                        ToastUtil.showShort(Pix.this,
                                String.format(Locale.ROOT, "Can't select more than %d items.", selectionList.size()));
                        return;
                    }
                    selectionList.add(img);
                    mInstantImageAdapter.select(true, position);
                    mMainImageAdapter.select(true, img);
                }
                if (selectionList.size() == 0) {
                    LongSelection = false;
                    selection_check.setVisibility(Component.VISIBLE);
                    try {
                        PixelMapElement pixelMapElement = null;
                        pixelMapElement =
                                new PixelMapElement(getResourceManager().getResource(ResourceTable.Media_back));
                        selection_back.setBackground(pixelMapElement);
                    } catch (IOException | NotExistException e) {
                        e.printStackTrace();
                    }
                    ShapeElement background = new ShapeElement();
                    background.setRgbColor(RgbColor.fromRgbaInt(Color.getIntColor("#ffffffff")));
                    topbar.setBackground(background);
                    sendButton.setVisibility(Component.HIDE);
                }
                selection_count.setText(selectionList.size() + " Selected");
                img_count.setText(String.valueOf(selectionList.size()));
            } else {
                selectionList.add(img);
                returnImages();
                try {
                    PixelMapElement pixelMapElement = null;
                    pixelMapElement = new PixelMapElement(getResourceManager().getResource(ResourceTable.Media_back));
                    selection_back.setBackground(pixelMapElement);
                } catch (IOException | NotExistException e) {
                    e.printStackTrace();
                }
                ShapeElement background = new ShapeElement();
                background.setRgbColor(RgbColor.fromRgbaInt(Color.getIntColor("#ffffffff")));
                topbar.setBackground(background);
            }
        }

        @Override
        public void onLongClick(Img img, Component view, int position) {
            if (options.getCount() > 1) {
                LongSelection = true;
                if (selectionList.size() == 0 && (mBottomSheet.getStatus() != MyBottomSheet.Status.ON_TOP)) {
                    sendButton.setVisibility(Component.VISIBLE);
                    sendButton.createAnimatorProperty()
                            .scaleXFrom(0).scaleX(1)
                            .scaleYFrom(0).scaleY(1)
                            .setDuration(300);
                }
                if (selectionList.contains(img)) {
                    selectionList.remove(img);
                    mInstantImageAdapter.select(false, position);
                    mMainImageAdapter.select(false, img);
                } else {
                    if (options.getCount() <= selectionList.size()) {
                        ToastUtil.showShort(Pix.this,
                                String.format(Locale.ROOT, "Can't select more than %d items.", selectionList.size()));
                        return;
                    }
                    selectionList.add(img);
                    mInstantImageAdapter.select(true, position);
                    mMainImageAdapter.select(true, img);
                }
                selection_check.setVisibility(Component.HIDE);
                ShapeElement background = new ShapeElement();
                background.setRgbColor(RgbColor.fromRgbaInt(Color.getIntColor("#075e54ff")));
                topbar.setBackground(background);
                selection_count.setText(selectionList.size() + " Selected");
                img_count.setText(String.valueOf(selectionList.size()));
                try {
                    PixelMapElement pixelMapElement = null;
                    pixelMapElement =
                            new PixelMapElement(getResourceManager().getResource(ResourceTable.Media_white_back));
                    selection_back.setBackground(pixelMapElement);
                } catch (IOException | NotExistException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    // 单帧捕获生成图像回调Listener
    private final ImageReceiver.IImageArrivalListener imageArrivalListener = new ImageReceiver.IImageArrivalListener() {
        @Override
        public void onImageArrival(ImageReceiver imageReceiver) {
            pictureName = Calendar.getInstance().getTimeInMillis() + ".jpg";
            // 创建图片文件
            File myFile = new File(picturePath, pictureName);
            // 创建一个读写线程任务用于保存图片
            ImageSaver imageSaver = new ImageSaver(imageReceiver.readNextImage(), myFile);
            // 执行读写线程任务生成图片
            cameraEventHandler.postTask(imageSaver);
            String absolutePath = null;
            try {
                absolutePath = myFile.getCanonicalPath();
            } catch (IOException e) {
                e.printStackTrace();
            }

            Img img = new Img("", "", absolutePath, "", "image/JPEG");
            img.setPixelMap(FileUtils.getPixMap(absolutePath));
            selectionList.add(img);

            returnImages();
        }
    };
    private final OnRecordStopListener mOnRecordStopListener = new OnRecordStopListener() {
        @Override
        public void onRecordStop(String filePath) {
            Img img = new Img("", "", filePath, "", "video/MPEG_4");
            img.setPixelMap(FileUtils.getFirstPixelMap(filePath));
            img.setMediaType("video/MPEG_4");
            selectionList.add(img);
            returnImages();
        }
    };

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        getWindow().setTransparent(true);
        getWindow().setBackgroundColor(new RgbColor(0xffffffff));
        setUIContent(ResourceTable.Layout_ability_take_picture);
        options = intent.getSerializableParam("options");
        if (options == null) {
            throw new SecurityException("options must not be null!");
        }
        File dir = getExternalFilesDir(options.getPath());
        if (!dir.exists()) {
            if (!dir.mkdir()) {
                // 创建文件夹失败
                terminateAbility();
            }
        }
        picturePath = dir + "/";
        initView();
    }

    private void initView() {
        setDisplayOrientation(options.getScreenOrientation());
        if (findComponentById(ResourceTable.Id_camera_view) instanceof CameraView) {
            cameraView = (CameraView) findComponentById(ResourceTable.Id_camera_view);
        }
        cameraView.setFrontCamera(options.isFrontfacing());
        cameraView.setMaxVideoDuration(options.getVideoDurationLimitinSeconds());
        cameraView.setImageArrivalListener(imageArrivalListener);
        cameraView.setOnRecordStopListener(mOnRecordStopListener);
        cameraView.setVideoPath(picturePath);
        if (findComponentById(ResourceTable.Id_take_pic_bg) instanceof Image) {
            takePicBg = (Image) findComponentById(ResourceTable.Id_take_pic_bg);
        }
        if (findComponentById(ResourceTable.Id_take_pic) instanceof Image) {
            takePic = (Image) findComponentById(ResourceTable.Id_take_pic);
        }
        takePic.setClickedListener(component -> {
            if (options.getMode() == Options.Mode.VIDEO) {
                return;
            }
            // 拍照
            cameraView.capture();
        });
        takePic.setTouchEventListener(new Component.TouchEventListener() {
            @Override
            public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
                if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_DOWN) {
                    takePicBg.setVisibility(Component.VISIBLE);
                }
                if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                    takePicBg.setVisibility(Component.HIDE);
                }
                if (cameraView.isRecording() && touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                    // 结束录像
                    cameraView.stopRecord();
                }
                return true;
            }
        });
        takePic.setLongClickedListener(component -> {
            // 录像
            if (options.getMode() == Options.Mode.PICTURE) {
                return;
            }
            cameraView.startRecord();
        });
        if (findComponentById(ResourceTable.Id_bottom_sheet) instanceof MyBottomSheet) {
            mBottomSheet = (MyBottomSheet) findComponentById(ResourceTable.Id_bottom_sheet);
        }
        if (findComponentById(ResourceTable.Id_sendButton) instanceof StackLayout) {
            sendButton = (StackLayout) findComponentById(ResourceTable.Id_sendButton);
        }
        sendButton.setClickedListener(this);
        horizontalList = mBottomSheet.getHorizontalList();
        verticalList = mBottomSheet.getVerticalList();
        selection_count = mBottomSheet.getSelectionCount();
        selection_back = mBottomSheet.getSelectionBack();
        selection_check = mBottomSheet.getSelectionCheck();
        selection_ok = mBottomSheet.getSelectionOk();
        arrow_up = mBottomSheet.getArrowUp();
        if (findComponentById(ResourceTable.Id_img_count) instanceof Text) {
            img_count = (Text) findComponentById(ResourceTable.Id_img_count);
        }
        if (findComponentById(ResourceTable.Id_fastscroll_scrollbar) instanceof StackLayout) {
            mScrollbar = (StackLayout) findComponentById(ResourceTable.Id_fastscroll_scrollbar);
        }
        topbar = mBottomSheet.getTopbar();
        if (findComponentById(ResourceTable.Id_bottomButtons) instanceof StackLayout) {
            bottomButtons = (StackLayout) findComponentById(ResourceTable.Id_bottomButtons);
        }
        if (findComponentById(ResourceTable.Id_flash) instanceof StackLayout) {
            flash = (StackLayout) findComponentById(ResourceTable.Id_flash);
        }
        if (findComponentById(ResourceTable.Id_front) instanceof StackLayout) {
            shiftCamera = (StackLayout) findComponentById(ResourceTable.Id_front);
        }
        flash.setClickedListener(this);
        shiftCamera.setClickedListener(this);
        selection_ok.setClickedListener(this);
        selection_check.setClickedListener(this);
        // 滑动监听
        mBottomSheet.setBottomSheetBehavior(this::onSlide);
        selection_back.setClickedListener(component -> {
            onBackPressed();
        });
        cameraEventHandler = new EventHandler(EventRunner.create("TakePictureAbilitySlice"));
        if (findComponentById(ResourceTable.Id_message_bottom) instanceof Text) {
            bottomMessage = (Text) findComponentById(ResourceTable.Id_message_bottom);
        }
        if (options.getMode() == Options.Mode.PICTURE) {
            bottomMessage.setText("Drag images up for gallery");
        } else if (options.getMode() == Options.Mode.VIDEO) {
            bottomMessage.setText("Drag videos up for gallery");
        } else {
            bottomMessage.setText("Hold for video, tap for photo");
        }
        initData();
    }

    private void initData() {
        mMainImageAdapter = new MainImageAdapter(this, options.getSpanCount());
        mMainImageAdapter.addOnSelectionListener(onVtcListListener);
        mInstantImageAdapter = new InstantImageAdapter(this);
        mInstantImageAdapter.addOnSelectionListener(onSelectionListener);
        horizontalList.setOrientation(Component.HORIZONTAL);
        mBottomSheet.setItemProvider(mInstantImageAdapter, mMainImageAdapter);
        mParallelTaskDispatcher = createParallelTaskDispatcher(dispatcherName, TaskPriority.DEFAULT);
        mRevocable = mParallelTaskDispatcher.asyncDispatch(new Runnable() {
            @Override
            public void run() {
                findPicture();
            }
        });
    }

    private void findPicture() {
        ResultSet resultSet = null;
        AVMetadataHelper avMetadataHelper = new AVMetadataHelper();
        try {
            DataAbilityHelper helper = DataAbilityHelper.creator(getContext());
            resultSet = Utility.getImageVideoResult(helper, options.getMode());
            if (resultSet != null) {
                int limit = 100;
                if (resultSet.getRowCount() < limit) {
                    limit = resultSet.getRowCount();
                }
                int pos = 0;
                String header = "";
                resultSet.goToLastRow();
                for (int i = 0; i < limit; i++) {
                    String data = resultSet.getString(resultSet
                            .getColumnIndexForName(AVStorage.Images.Media.DATA));
                    String mediaType = resultSet.getString(resultSet
                            .getColumnIndexForName(AVStorage.Images.Media.MIME_TYPE));
                    int contentUrl = resultSet.getInt(resultSet
                            .getColumnIndexForName(AVStorage.Images.Media.ID));
                    Uri path = null;
                    PixelMap pixelMap;
                    if (mediaType.contains("image")) {
                        path = Uri.appendEncodedPathToUri(AVStorage.Images.Media.EXTERNAL_DATA_ABILITY_URI,
                                "" + contentUrl);
                        FileDescriptor filedesc = helper.openFile(path, "r");
                        ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
                        ImageSource imageSource = ImageSource.create(filedesc, null);
                        pixelMap = imageSource.createThumbnailPixelmap(decodingOpts, true);
                    } else if (mediaType.contains("video")) {
                        path = Uri.appendEncodedPathToUri(AVStorage.Video.Media.EXTERNAL_DATA_ABILITY_URI,
                                "" + contentUrl);
//                        pixelMap = FileUtils.getFirstPixelMap(data);
                        LogUtil.loge("pathUri = " + contentUrl);
                        FileDescriptor fileDescriptor = helper.openFile(path, "r");
                        avMetadataHelper.setSource(fileDescriptor);
                        pixelMap = avMetadataHelper.fetchVideoPixelMapByIndex(0);
                    } else {
                        resultSet.goToPreviousRow();
                        continue;
                    }
                    if (pixelMap != null) {
                        pixelMap = compressPixelMap(pixelMap);
                    }
                    Calendar calendar;
                    calendar = Calendar.getInstance();
                    int imageDate = resultSet.getInt(resultSet
                            .getColumnIndexForName(AVStorage.Images.Media.DATE_MODIFIED));
                    calendar.setTimeInMillis(((long) (imageDate)) * 1000);
                    String dateDifference = Utility.getDateDifference(calendar);
                    if (!header.equalsIgnoreCase("" + dateDifference)) {
                        header = "" + dateDifference;
                        pos += 1;
                        mList.add(new Img("" + dateDifference, "", "", "", mediaType));
                    }
                    Img img =
                            new Img("" + header, "" + path, data, "" + pos, mediaType);
                    img.setPosition(pos);
                    img.setPixelMap(pixelMap);
                    String fileName = resultSet.getString(resultSet
                            .getColumnIndexForName(AVStorage.Images.Media.DISPLAY_NAME));
                    String filePath = picturePath + fileName;
                    if (options.getPreSelectedUrls().contains(img.getContentUrl())
                            || options.getPreSelectedUrls().contains(filePath)) {
                        img.setSelected(true);
                        selectionList.add(img);
                    }
                    pos += 1;
                    mList.add(img);
                    resultSet.goToPreviousRow();
                }
                resultSet.close();
            }
        } catch (DataAbilityRemoteException | FileNotFoundException e) {
            e.printStackTrace();
        }
        mHandler.sendEvent(NOTIFY_PROVIDER);
    }

    /**
     * MyBottomSheet 滑动的监听
     *
     * @param slideOffset 滑动的百分比
     */
    public void onSlide(double slideOffset) {
        Utility.manipulateVisibility(slideOffset, arrow_up,
                horizontalList, verticalList,
                topbar, bottomButtons, sendButton, LongSelection);
    }

    @Override
    public void onClick(Component component) {
        int id = component.getId();
        if (id == ResourceTable.Id_sendButton || id == ResourceTable.Id_selection_ok) {
            // 点击选完按钮
            returnImages();
        }
        if (id == ResourceTable.Id_selection_check) {
            ShapeElement shapeElement = new ShapeElement();
            shapeElement.setRgbColor(RgbColor.fromArgbInt(new Color(ResourceTable.Color_colorPrimaryPix).getValue()));
            topbar.setBackground(shapeElement);
            selection_count.setText(ResourceTable.String_pix_tap_to_select);
            img_count.setText(String.valueOf(selectionList.size()));
            try {
                PixelMapElement pixelMapElement = null;
                pixelMapElement =
                        new PixelMapElement(getResourceManager().getResource(ResourceTable.Media_white_back));
                selection_back.setBackground(pixelMapElement);
            } catch (IOException | NotExistException e) {
                e.printStackTrace();
            }
            LongSelection = true;
            selection_check.setVisibility(Component.HIDE);
        }
        if (id == ResourceTable.Id_flash) {
            // 闪光灯
            int height = flash.getHeight();
            if (flash.getComponentAt(0) instanceof Image) {
                Image iv = (Image) flash.getComponentAt(0);
                flash.createAnimatorProperty().moveToY(height).setDuration(100)
                        .setStateChangedListener(new Animator.StateChangedListener() {
                            @Override
                            public void onStart(Animator animator) {
                            }

                            @Override
                            public void onStop(Animator animator) {
                            }

                            @Override
                            public void onCancel(Animator animator) {
                            }

                            @Override
                            public void onEnd(Animator animator) {
                                iv.setTranslationY(-(height / 2));
                                if (flashMode == Metadata.FlashMode.FLASH_AUTO) {
                                    flashMode = Metadata.FlashMode.FLASH_CLOSE;
                                    try {
                                        PixelMapElement flashDrawable =
                                                new PixelMapElement(getResourceManager()
                                                        .getResource(ResourceTable.Media_flash_off));
                                        iv.setBackground(flashDrawable);
                                    } catch (IOException | NotExistException e) {
                                        e.printStackTrace();
                                    }
                                } else if (flashMode == Metadata.FlashMode.FLASH_CLOSE) {
                                    flashMode = Metadata.FlashMode.FLASH_ALWAYS_OPEN;
                                    try {
                                        PixelMapElement flashDrawable =
                                                new PixelMapElement(getResourceManager()
                                                        .getResource(ResourceTable.Media_flash_on));
                                        iv.setBackground(flashDrawable);
                                    } catch (IOException | NotExistException e) {
                                        e.printStackTrace();
                                    }
                                } else {
                                    flashMode = Metadata.FlashMode.FLASH_AUTO;
                                    try {
                                        PixelMapElement flashDrawable =
                                                new PixelMapElement(getResourceManager()
                                                        .getResource(ResourceTable.Media_flash_auto));
                                        iv.setBackground(flashDrawable);
                                    } catch (IOException | NotExistException e) {
                                        e.printStackTrace();
                                    }
                                }
                                cameraView.setCameraFlashMode(flashMode);
                                iv.createAnimatorProperty().moveToY(0).setDuration(50)
                                        .setStateChangedListener(null).start();
                            }

                            @Override
                            public void onPause(Animator animator) {
                            }

                            @Override
                            public void onResume(Animator animator) {
                            }
                        }).start();
            }
        }
        if (id == ResourceTable.Id_front) {
            // 切换摄像头
            AnimatorProperty animatorProperty = shiftCamera.createAnimatorProperty();
            animatorProperty.scaleXFrom(1).scaleX(0).setDuration(150)
                    .setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {
                }

                @Override
                public void onStop(Animator animator) {
                }

                @Override
                public void onCancel(Animator animator) {
                }

                @Override
                public void onEnd(Animator animator) {
                    animatorProperty.scaleXFrom(0).scaleX(1).setDuration(150)
                            .setStateChangedListener(null).start();
                }

                @Override
                public void onPause(Animator animator) {
                }

                @Override
                public void onResume(Animator animator) {
                }
            }).start();
            cameraView.switchCamera();
        }
    }

    private void returnImages() {
        ArrayList<Img> list = new ArrayList<>();
        for (Img img : selectionList) {
            img.setPixelMap(null);
            list.add(img);
        }
        Intent resultIntent = new Intent();
        resultIntent.setSequenceableArrayListParam(Pix.IMAGE_RESULTS, list);
        setResult(options.getRequestCode(), resultIntent);
        terminateAbility();
    }

    /**
     * 开启Pix
     *
     * @param abilitySlice abilitySlice
     * @param options      options
     */
    public static void start(AbilitySlice abilitySlice, Options options) {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName(abilitySlice.getBundleName())
                .withAbilityName(Pix.class.getName())
                .build();
        intent.setOperation(operation);
        intent.setParam("options", options);
        abilitySlice.startAbilityForResult(intent, options.getRequestCode());
    }

    /**
     * 开启Pix
     *
     * @param ability ability
     * @param options options
     */
    public static void start(Ability ability, Options options) {
        Intent intent = new Intent();
        Operation operation = new Intent.OperationBuilder()
                .withDeviceId("")
                .withBundleName(ability.getBundleName())
                .withAbilityName(Pix.class.getName())
                .build();
        intent.setOperation(operation);
        intent.setParam("options", options);
        ability.startAbilityForResult(intent, options.getRequestCode());
    }

    /**
     * 开启Pix
     *
     * @param ability     ability
     * @param requestCode requestCode
     */
    public static void start(Ability ability, int requestCode) {
        start(ability, Options.init().setRequestCode(requestCode).setCount(1));
    }

    @Override
    public void onActive() {
        super.onActive();
        ComponentContainer.LayoutConfig layoutConfig = mBottomSheet.getLayoutConfig();
        layoutConfig.height = mBottomSheet.getMinHeight();
        mBottomSheet.setLayoutConfig(layoutConfig);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // 取消异步任务
        if (mRevocable != null) {
            mRevocable.revoke();
        }
        if (mParallelTaskDispatcher != null) {
            mParallelTaskDispatcher = null;
        }
    }

    @Override
    protected void onBackPressed() {
        if (mBottomSheet.getStatus() != MyBottomSheet.Status.ON_FOLD) {
            // 折叠
            mBottomSheet.gotoFold();
        } else {
            super.onBackPressed();
        }
    }

    private class MyEventHandler extends EventHandler {
        private MyEventHandler(EventRunner runner) {
            super(runner);
        }

        // 重写实现processEvent方法
        @Override
        public void processEvent(InnerEvent event) {
            super.processEvent(event);
            if (event.eventId == NOTIFY_PROVIDER) {
                if (selectionList.size() > 0) {
                    LongSelection = true;
                    sendButton.setVisibility(Component.VISIBLE);
                    selection_check.setVisibility(Component.HIDE);
                    ShapeElement background = new ShapeElement();
                    background.setRgbColor(RgbColor.fromRgbaInt(Color.getIntColor("#075e54ff")));
                    topbar.setBackground(background);
                    selection_count.setText(selectionList.size() + " Selected");
                    img_count.setText(String.valueOf(selectionList.size()));
                    try {
                        PixelMapElement pixelMapElement = null;
                        pixelMapElement =
                                new PixelMapElement(getResourceManager().getResource(ResourceTable.Media_white_back));
                        selection_back.setBackground(pixelMapElement);
                    } catch (IOException | NotExistException e) {
                        e.printStackTrace();
                    }
                }
                if (mList.size() == 0) {
                    arrow_up.setVisibility(Component.INVISIBLE);
                } else {
                    arrow_up.setVisibility(Component.VISIBLE);
                }
                mInstantImageAdapter.setList(mList);
                mMainImageAdapter.setList(mList);
                mBottomSheet.setItemProvider(mInstantImageAdapter, mMainImageAdapter);
                int providerHeight = mMainImageAdapter.getProviderHeight();
                mBottomSheet.setMaxHeight(providerHeight);
            }
        }
    }

    // 保存图片, 图片数据读写，及图像生成见run方法
    private class ImageSaver implements Runnable {
        private final ohos.media.image.Image myImage;
        private final File myFile;

        ImageSaver(ohos.media.image.Image image, File file) {
            myImage = image;
            myFile = file;
        }

        @Override
        public void run() {
            ohos.media.image.Image.Component component = myImage.getComponent(ImageFormat.ComponentType.JPEG);
            byte[] bytes = new byte[component.remaining()];
            component.read(bytes);
            FileOutputStream output = null;
            try {
                output = new FileOutputStream(myFile);
                // 写图像数据
                output.write(bytes);
                output.flush();
                FileUtils.saveImageToGallery(pictureName,
                        FileUtils.getPixMap(myFile.getCanonicalPath()), Pix.this);
            } catch (IOException e) {
                LogUtil.loge("save picture occur exception!" + e.getLocalizedMessage());
            } finally {
                myImage.release();
                if (output != null) {
                    try {
                        // 关闭流
                        output.close();
                    } catch (IOException e) {
                        LogUtil.loge("image release occur exception!");
                    }
                }
            }
            ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
            sourceOptions.formatHint = "image/jpg";
            ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
            decodingOptions.desiredPixelFormat = PixelFormat.ARGB_8888;
        }
    }

    private PixelMap compressPixelMap(PixelMap pixelMap) {
        int width = pixelMap.getImageInfo().size.width;
        int height = pixelMap.getImageInfo().size.height;
        // 压缩缩略图
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        initializationOptions.size = new Size(width / 3, height / 3);
        initializationOptions.releaseSource = true;
        PixelMap resultPixelMap = PixelMap.create(pixelMap, initializationOptions);
        // 如果没有缩放，那么不回收
        if (pixelMap != resultPixelMap) {
            // 释放Bitmap的native像素数组
            pixelMap.release();
        }
        return resultPixelMap;
    }
}
